import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.JFrame;
import cern.colt.Timer;
import edu.uci.ics.jung.algorithms.layout.*;
import edu.uci.ics.jung.graph.*;
import edu.uci.ics.jung.visualization.BasicVisualizationServer;

public class main {
	public static double[] LifeTimeProb = new double[100];
	public static int INIT_NODE_AMOUNT = 100;
	public static int TERMINATE_COND = 10000;
	public static int NODE_AMOUNT = 20;
	public static int EDGE_AMOUNT = 30;
	public static int AGE_MAX = 80;
	public static double IMMIGRANT_RATE = (double)0.1;
	public static float DEATH_RATE = (float) 0.06;
	public static float BORN_RATE = (float) 0.07; 
	public static int AGE_INTERVAL = 10; 
	public static int TOTAL_AGE = 100;
	public static int[] deathToll = new int[TOTAL_AGE];
	public static double immiRate = IMMIGRANT_RATE;
	public static ArrayList<MyNode> nodelist = new ArrayList<MyNode>();
	
	public static void readLifeTime(){
		int LifeAge=0;
		try{
			// Open the file that is the first 
			// command line parameter
			FileInputStream fstream = new FileInputStream("/LifeTimeDistribution");
			// Get the object of DataInputStream
			DataInputStream in = new DataInputStream(fstream);
	        BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine = null;
			
			//Read File Line By Line
			while ((strLine = br.readLine()) != null) 	{
				// Print the content on the console
				// System.out.println (strLine);
				LifeTimeProb[LifeAge] = Double.parseDouble(strLine);
				LifeAge++;
			}
			in.close();
			}catch (Exception e){//Catch exception if any
				System.err.println("Error: " + e.getMessage());
		}
	}
	
	public static void AnnualUpdate(ArrayList<MyNode> nodelist){
		for(int i=0; i<nodelist.size(); i++){
			nodelist.get(i).age++;
		}
		for(int i=0;i<TOTAL_AGE;i++){
			deathToll[i] = (int) (DEATH_RATE * nodelist.size() * LifeTimeProb[i]);
		}
		immiRate *= (double)((TERMINATE_COND-nodelist.size()) / TERMINATE_COND); 
		// TODO add link to the graph
	}

	public static void deathFunction(ArrayList<MyNode> nlist, UndirectedGraph x ){
		int index=0;
		int index_f=0;
		int index_b=0;
		int tempkillAge=0;
		if(index<=nodelist.size()){
		for(int killAge=0;killAge<TOTAL_AGE;killAge++){
//			tempkillAge = killAge;
			for(int j=0;j<deathToll[killAge]&&deathToll[killAge]!=0;j++){
//				System.out.println(killAge+"歲要殺"+deathToll[killAge]+"個人");
				System.out.println("\nindex position_before: " + index);
				while(true){
					if(nlist.get(index).age < killAge){ 
						index++;
//						while(nlist.get(index).age>killAge) tempkillAge++; //  沒人可殺或跳號
//					else if(nlist.get(index).age > killAge) index--;
					}else //if(nlist.get(index).age > killAge)
						break;
				}
				System.out.println("index position_after: " + index);
				System.out.println(killAge+"歲要殺"+deathToll[killAge]+"個人");
				
				index_f = index-1;
				index_b = index+1;
//				System.out.println("check killing: index="+index_f+"號人是"+nlist.get(index-1).age+"歲");
				System.out.println("check killing: index="+index+"號人是"+nlist.get(index).age+"歲");
				System.out.println("check killing: index="+index_b+"號人是"+nlist.get(index+1).age+"歲");
//					System.out.println("index:" + index);
					if( nlist.get(index).age == killAge && deathToll[killAge]!=0){		
						System.out.println("before killing: index="+index+"號人是"+nlist.get(index).age+"歲");

					
						x.removeVertex( nodelist.get(index) );
						nodelist.remove(index);
						System.out.println("我殺掉了" + index + "號, 年齡是" + killAge + ". 現在尚有" + nodelist.size() + "人");
						System.out.println("after killing: index="+index+"號人是"+nlist.get(index).age+"歲");
					}
			}	
		}
		}
	}
	
	public static void main(String[] args) {
		int source, target;
		int nowYear=1;
		
		UndirectedGraph x = new UndirectedSparseGraph();		

		MyNode NodeTemp;
		int TotalAge=0;

		readLifeTime();
				
		for(int i=0;i<INIT_NODE_AMOUNT;i++){		
			x.addVertex(NodeTemp =  new MyNode(i, (int)(Math.random()*AGE_MAX+1) ) );
			nodelist.add( NodeTemp );
		}
		
		
		/* start life */
		while(nodelist.size() < TERMINATE_COND ){
			nowYear++;
			System.out.println("IRLAB YEAR " + nowYear);
			int i=0;
						
			/* calculate the population import*/
			for(i=0;i<nodelist.size()*BORN_RATE;i++){
				x.addVertex(NodeTemp =  new MyNode(i, 0) );
				nodelist.add(NodeTemp);
			}
			System.out.println("生了 "+ i);
			
			for(i=0;i<nodelist.size()*immiRate;i++){
				x.addVertex(NodeTemp =  new MyNode(i, (int)Math.random()*AGE_MAX+1) );
				nodelist.add(NodeTemp);
				//TODO update IMMIGRANT_RATE
			}
			System.out.println("進來了 "+ i);			
								
			/* kill person*/
			Collections.sort(nodelist);
			deathFunction(nodelist, x);
			AnnualUpdate(nodelist);		
			System.out.println("POPULATION: " + nodelist.size());
		}
		
		
		//System.out.println("the Graph g=" + x.toString() + "edge:" + x.getEdgeCount() );
		TotalAge = 0;
		for(int i=0;i<nodelist.size() ;i++){
				TotalAge += nodelist.get(i).age;			
		}
		System.out.println("\n\nAverage Age : "+ (double)TotalAge / nodelist.size());
		
//		for(int i=0;i<nodelist.size();i++){
//			System.out.println(nodelist.get(i));
//		}
		
		/*
		Layout<Integer, String> layout = new CircleLayout(x);
		layout.setSize(new Dimension(400,400)); // sets the initial size of the space
	     // The BasicVisualizationServer<V,E> is parameterized by the edge types
	    BasicVisualizationServer<Integer,String> vv = 
	              new BasicVisualizationServer<Integer,String>(layout);
	    vv.setPreferredSize(new Dimension(500,500)); //Sets the viewing area size
	    
	    JFrame frame = new JFrame("Simple Graph View");
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.getContentPane().add(vv); 
	    frame.pack();
	    frame.setVisible(true);
		*/	
	}

	
}
